package listen.event;

import listen.beans.BeansException;
import listen.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;

public class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactory {
    final Set<ApplicationListener<ApplicationEvent>>  applicationListeners = new LinkedHashSet<>();
    BeanFactory beanFactory;

    @Override
    public Object getBean(String name) throws BeansException {
        return null;
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return null;
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return null;
    }

    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        applicationListeners.add((ApplicationListener<ApplicationEvent>) listener);
    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {
        applicationListeners.remove((ApplicationListener<ApplicationEvent>) listener);
    }

    @Override
    public void multicastEvent(ApplicationListener<?> listener) {

    }

    Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) throws Exception {
        LinkedList<ApplicationListener> list = new LinkedList<>();
        for(ApplicationListener<ApplicationEvent> listener:list){
            if(supportsEvent(listener,event)){
               listener.onApplicationEvent((ApplicationEvent) listener);
            }
        }
        return list;
    }


    /**
     * 监听器是否对该事件感兴趣
     * @param applicationListener
     * @param event
     * @return
     */
    boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) throws Exception {
        Class<? extends ApplicationListener> lstenerClass = applicationListener.getClass();
        // 按照CglibSubclassingInstantiationStrategy、SimpleInstantiationStrategy 不同的实例化类型，需要判断后获取目标class
        Class<?> targetClass = ClassUtils.isCglibProxyClass(lstenerClass)?lstenerClass.getSuperclass():lstenerClass;
        Type gener = targetClass.getGenericInterfaces()[0];
        Type actualType = gener.getTypeName().getClass();

        String className = actualType.getTypeName();
        Class<?> eventClass;
        try{
            eventClass = Class.forName(className);
        }catch (Exception e){
            throw new Exception(className+"not found");
        }
        // 判定此eventClassName对象所表示的类或接口与指定的event。getclass()参数所表示的类或接口是否相同，或是否是其超类或超接口
        // isAssignableFrom判断子类和父类的关系，或者接口的实现类和接口的关系，默认所有的类的终极父类都是Object.如果A.isAssignableFrom(B)结果是true，证明B可以转换成为A,也就是A可以由B转换而来。
        return eventClass.isAssignableFrom(event.getClass());


    }
}
